﻿//     Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using Microsoft.Gateway.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Microsoft.Gateway.Configuration
{
    public static class ConfigurationLoader
    {
        public static RulesConfiguration ReadFromSource(string indexLocation)
        {
            if (String.IsNullOrWhiteSpace(indexLocation))
            {
                throw new ArgumentNullException("indexLocation", "No value specified for stored configuration index location");
            }
            Uri indexUri;
            if (!Uri.TryCreate(indexLocation, UriKind.Absolute, out indexUri))
            {
                throw new ArgumentException(String.Format("Specified configuration index location is invalid: [{0}]", indexLocation));
            }
            var infoHeaders = new Dictionary<string, string>
            {
                { ApiUriBuilder.QueryParamCurrentVersion, Assembly.GetCallingAssembly().GetName().Version.GatewayFormat() },
            };
            GatewayConfigurationIndex parsedIndex = null;
            try
            {
                parsedIndex = JsonLoader.ReadObject<GatewayConfigurationIndex>(indexUri, infoHeaders);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Failed to read remote configuration index.", ex);
            }
            var retval = new RulesConfiguration();
            foreach (var roleIndex in parsedIndex.Roles)
            {
                Uri roleConfigUri;
                if (!Uri.TryCreate(roleIndex.Value, UriKind.Absolute, out roleConfigUri))
                {
                    Trace.TraceWarning("Index configuration for role [{0}] does not point to a valid location [{1}]. This role will not be processed.",
                        roleIndex.Key, roleIndex.Value);
                }
                else
                {
                    try
                    {
                        var roleConfig = JsonLoader.ReadObject<Role>(roleConfigUri, infoHeaders);
                        roleConfig.Segment = roleIndex.Key;
                        retval.Roles[roleIndex.Key] = roleConfig;
                    }
                    catch 
                    {
                        // Details of exception have already been logged
                        Trace.TraceWarning("Failed to read role configuration for role [{0}]. This role will not be processed.", roleIndex.Key);
                    }
                }
            }
            retval.Directory = parsedIndex.Directory;
            retval.ApplicationName = parsedIndex.ApplicationName;
            return retval;
        }

        public static RulesConfiguration ReadFromCache(string cachePath)
        {
            return SharedCache.ReadCachedObject<RulesConfiguration>(SharedCache.CacheClasses.GatewayConfiguration, cachePath);
        }

        public static bool WriteToCache(RulesConfiguration configuration, string cachePath)
        {
            return SharedCache.WriteObjectToCache(SharedCache.CacheClasses.GatewayConfiguration, configuration, cachePath);
        }
    }
}
